﻿using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ImportPlcPointPosition.Core
{
    // 表示元素的类
    public class Element
    {
        public int Id { get; set; }
        public int ParentId { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }


        public string Comment { get; set; }
        public List<Element> Children { get; set; } = new List<Element>();

        public override string ToString()
        {
            return $"Id: {Id}, ParentId: {ParentId}, Name: {Name}, Type: {Type}, Comment: {Comment}";
        }
    }

    // 解析器类
    public class S7CodeParser
    {
        private int currentId = 1;

        public List<Element> Parse(string code)
        {
            var elements = new List<Element>();
            var lines = code.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
            var stack = new Stack<Element>();

            foreach (var line in lines.Select(l => l.Trim()))
            {
                // 跳过版本信息行
                if (line.StartsWith("VERSION :"))
                {
                    continue;
                }
                // 在开始处理每行时就移除 { S7_SetPoint := 'False' } 标记
                //Name: L1                { S7_SetPoint := 'False'}
                var cleanLine = Regex.Replace(line, @"\{ S7_SetPoint := 'False'\}", "").Trim();

                if (cleanLine.StartsWith("TYPE"))
                {
                    // 处理 TYPE 部分，去掉可能的分号
                    var typeName = Regex.Match(cleanLine, @"TYPE ""([^""]+)""").Groups[1].Value;
                    var newElement = new Element { Id = Interlocked.Increment(ref currentId) - 1, Name = typeName, Type = "TYPE" };
                    elements.Add(newElement);
                    stack.Push(newElement);
                }
                else if (cleanLine.StartsWith("DATA_BLOCK"))
                {
                    var dataBlockName = Regex.Match(cleanLine, @"DATA_BLOCK ""([^""]+)""").Groups[1].Value;
                    var newElement = new Element { Id = Interlocked.Increment(ref currentId) - 1, Name = dataBlockName, Type = "DATA_BLOCK" };
                    elements.Add(newElement);
                    stack.Push(newElement);
                }
                else if (cleanLine.Contains(": Struct"))
                {
                    var parts = cleanLine.Split(new[] { ':' }, 2);
                    var name = parts[0].Trim();
                    var commentMatch = Regex.Match(parts[1], @"//(.*)");
                    var comment = commentMatch.Success ? commentMatch.Groups[1].Value.Trim() : "";

                    var structElement = new Element { Id = Interlocked.Increment(ref currentId) - 1, Name = name, Type = "STRUCT", Comment = comment };
                    if (stack.Count > 0)
                    {
                        structElement.ParentId = stack.Peek().Id;
                        stack.Peek().Children.Add(structElement);
                    }
                    stack.Push(structElement);
                }
                else if (cleanLine.StartsWith("STRUCT"))
                {
                    if (stack.Count > 0)
                    {
                        var structElement = new Element { Id = Interlocked.Increment(ref currentId) - 1, Name = "AnonymousStruct", Type = "STRUCT" };
                        structElement.ParentId = stack.Peek().Id;
                        stack.Peek().Children.Add(structElement);
                        stack.Push(structElement);
                    }
                }
                else if (cleanLine.StartsWith("END_STRUCT"))
                {
                    if (stack.Count > 0)
                    {
                        stack.Pop();
                    }
                }
                else if (cleanLine.Contains(":") && stack.Count > 0)
                {
                    var parts = cleanLine.Split(new[] { ':' }, 2);
                    var name = parts[0].Trim();
                    var typeAndComment = parts[1].Trim();
                    var commentMatch = Regex.Match(typeAndComment, @"//(.*)");
                    var comment = commentMatch.Success ? commentMatch.Groups[1].Value.Trim() : "";
                    var type = commentMatch.Success
                       ? typeAndComment.Substring(0, typeAndComment.IndexOf("//")).Trim().Replace(";", "")
                        : typeAndComment.Replace(";", "").Trim();
                    // 去掉类型名称首尾的双引号
                    if (type.StartsWith("\"") && type.EndsWith("\""))
                    {
                        type = type.Substring(1, type.Length - 2);
                    }
                    var newElement = new Element { Id = Interlocked.Increment(ref currentId) - 1, Name = name, Type = type, Comment = comment };
                    newElement.ParentId = stack.Peek().Id;
                    stack.Peek().Children.Add(newElement);
                }
            }

            return elements;
        }


        public void ExpandCustomTypes(List<Element> elements)
        {
            var typeElements = elements.Where(e => e.Type == "TYPE").ToDictionary(e => e.Name, e => e);
            int localCurrentId = currentId;

            void RecursiveExpand(Element parent)
            {
                foreach (var child in parent.Children.ToList())
                {
                    if (typeElements.ContainsKey(child.Type))
                    {
                        var customType = typeElements[child.Type];
                        foreach (var subChild in customType.Children[0].Children)
                        {
                            var newChild = new Element
                            {
                                // 为子元素重新创建 ID
                                Id = Interlocked.Increment(ref localCurrentId) - 1,
                                ParentId = child.Id,
                                Name = subChild.Name,
                                Type = subChild.Type,
                                Comment = subChild.Comment,
                                Children = subChild.Children.Adapt<List<Element>>()
                            };
                            child.Children.Add(newChild);
                            RecursiveExpand(newChild);
                        }
                    }
                    RecursiveExpand(child);
                }
            }

            foreach (var element in elements)
            {
                RecursiveExpand(element);
            }
            currentId = localCurrentId;
        }

        public void FixIdsAndParentIds(List<Element> elements)
        {
            int newId = 1;
            var idMapping = new Dictionary<int, int>();

            void RecursiveFix(Element element, int parentId = 0)
            {
                idMapping[element.Id] = newId;
                element.Id = newId++;
                element.ParentId = parentId;

                foreach (var child in element.Children)
                {
                    RecursiveFix(child, element.Id);
                }
            }

            foreach (var element in elements)
            {
                RecursiveFix(element, 0);
            }
        }
    }
}
